﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Security.Permissions;
using System.Threading;
using Microsoft.Live;
using Schedule;
using WPFExcelReport;
namespace SkyDriveAPI
{
    public class Watcher
    {
        public string ApplicationPath
        {
            get { return System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath); }
        }
        private ScheduleTimer _AlarmTimer = new ScheduleTimer();
        DataTable tbFileList = null;
        DataSet SetUser;
        private Config _Config;
        string file = "";
        public Queue<KeyValuePair<string, string>> jobQ = null;
        string RemoteName = "";
        List<string> watchpath = new List<string>();
        LiveConnectClient client;
        ArrayList folders = new ArrayList();
        int running = 0;
        System.Threading.Timer DailyTimer;
        System.Threading.Timer WeeksTimer;
        public LiveConnectClient LiveClient
        {
            get
            {
                return client;
            }
            set
            {
                client = value;
                foreach (string folder in folders)
                {
                    client.GetFolderID(folder);
                }
            }
        }
        string company = "HLT";
        string user = "WPSVC";
        delegate void TickHandler(DateTime tick);
        public delegate void ReportEventHandler(object sender, ReportEventArgs e);
        BATCHVKVV BATCHVKVV;
        public Watcher(bool readconfig=true)
        {
            if (readconfig)
            {
                ReadConfig();
                _Config = new Config("PhoneServiceWF.exe.config");
                company = _Config.GetSettingDefault("Company", "HLT");
                user = _Config.GetSettingDefault("User", "WPSVC");
                LoadSetSETUP(company, user);
                StartQueueWork();
                StartWatcher(watchpath);
            }
            //从现在开始，到明天的1：00，多少小时            
        }
        private void StartQueueWork()
        {
            try
            {
                _AlarmTimer.Stop();
                _AlarmTimer.ClearJobs();
                DateTime StartTime=DateTime.Now;
                TimeSpan span = TimeSpan.FromDays(1);
                IScheduledItem item;
                ScheduledTime AlarmTime;
                foreach (DataRow row in SetUser.Tables["MENU"+user].Rows)
                {
                    string TYPE=row["TYPE"].ToString();
                    string FREQUENCY = row["FREQUENCY"].ToString();
                    string offset= row["TIME"].ToString();
                    string job = row["JOB"].ToString();
                    switch(TYPE)
                    {
                        case"SimpleInterval":
                            break;
                        case "ScheduledTimer": 
                            break;
                        case "SingleEvent":
                            offset = System.DateTime.Now.AddMinutes(System.Convert.ToInt16(offset)).ToString();;
                            AlarmTime = new ScheduledTime("Daily", offset);
                            SetAlarmTimer(AlarmTime,job);
                            break;
                        case "AlarmTimer":
                            AlarmTime = new ScheduledTime(FREQUENCY, offset);
                            SetAlarmTimer(AlarmTime,job);
                            break;
                        default:
                            break;
                    }
                }
                _AlarmTimer.Start();
            }
            catch (Exception ex)
            { 
            }
        }
        private void SetAlarmTimer(ScheduledTime AlarmTime,string job)
        {
            switch (job)
            {
                case "GetSkyDriveFileList":
                    _AlarmTimer.AddAsyncJob(AlarmTime, new TickHandler(_GetSkyDriveFileList));
                    break;
                case "BATCHVKVV":
                    _AlarmTimer.AddAsyncJob(AlarmTime, new TickHandler(_BATCHVKVV));
                    break;
                case "BATCHUPLOAD":
                    _AlarmTimer.AddAsyncJob(AlarmTime, new TickHandler(_BATCHUPLOAD));
                    break; 
                case "DAILYUPDATE":
                    _AlarmTimer.AddAsyncJob(AlarmTime, new TickHandler(_DAILYUPDATE));
                    break;
                case "WEEKLYUPDATE":
                    _AlarmTimer.AddAsyncJob(AlarmTime, new TickHandler(_WEEKLYUPDATE));
                    break;
                case "MONTHLYUPDATE":
                    _AlarmTimer.AddAsyncJob(AlarmTime, new TickHandler(_MONTHLYUPDATE));
                    break;
                case "DAILYMORNING":
                    _AlarmTimer.AddAsyncJob(AlarmTime, new TickHandler(_DAILYMORNING));
                    break;
                case "DAILYNOON":
                    _AlarmTimer.AddAsyncJob(AlarmTime, new TickHandler(_DAILYNOON));
                    break;
                case "DAILYSUMMARY":
                    _AlarmTimer.AddAsyncJob(AlarmTime, new TickHandler(_DAILYSUMMARY));
                    break;
                default:
                    break;
            }            
        }
        private void _MONTHLYUPDATE(DateTime time)
        {
            MONTHLYUPDATE.BatchLoadIntexKeyTable();
        }
        private void _DAILYMORNING(DateTime time)
        {
            DAILYMORNING.BatchLoadIntexKeyTable();
        }
        private void _DAILYNOON(DateTime time)
        {
            DAILYNOON.BatchLoadIntexKeyTable();
        }
        private void _DAILYSUMMARY(DateTime time)
        {
            DAILYSUMMARY.BatchLoadIntexKeyTable();
        }
        private void _WEEKLYUPDATE(DateTime time)
        {
            WEEKLYUPDATE.BatchLoadIntexKeyTable();
        }
        private void _DAILYUPDATE(DateTime time)
        {
            DAILYUPDATE.BatchLoadIntexKeyTable("EQ");
        }
        private void _BATCHUPLOAD(DateTime time)
        {
            BATCHUPLOAD.BatchLoadIntexKeyTable();
        }
        public void _BATCHVKVV(DateTime time)
        {
            if (BATCHVKVV == null)
                BATCHVKVV = new BATCHVKVV(null,null);
            BATCHVKVV.Execute();
        }
        private void _GetSkyDriveFileList(DateTime time)
        {
            BATCHUPLOAD.GetSkyDriveFileList();
        }        
        public DataSet LoadSetSETUP(string company, string user)
        {
            DataSet setReturn = new DataSet();
            DataSet setResult = new DataSet();
            SetUser = new DataSet();
            string filePath = "";
            try
            {
                ArrayList tables = new ArrayList();
                string fileroot = ApplicationPath + @"\Documents\";
                tables.Add("FUNCTION");
                tables.Add("MENU" + user.Trim());
                foreach (string tbname in tables)
                {
                    filePath = fileroot + tbname + ".XML";
                    if (System.IO.File.Exists(filePath))
                    {
                        setResult = new DataSet();
                        setResult.ReadXml(filePath);
                        SetUser.Merge(setResult);
                    }
                }
                if (SetUser.Tables.Contains("FUNCTION"))
                {
                    tbFileList = SetUser.Tables["FUNCTION"];
                }
            }
            catch (Exception ex)
            {

            }
            return setReturn;
        }
        public void StartWatcher(List<string> watchpaths)
        {
            foreach (string watchpath in watchpaths)
            {
                if (System.IO.Directory.Exists(watchpath))
                {
                    DirectoryInfo root = new DirectoryInfo(watchpath);
                    FileInfo[] files = root.GetFiles();
                    DirectoryInfo[] sub = root.GetDirectories();
                    try
                    {
                        /*for (int i = 0; i < files.Length; i++)
                        {
                            //System.IO.File.Delete(files[i].ToString());
                        }*/
                        for (int i = 0; i < sub.Length; i++)
                        {
                            folders.Add(sub[i].ToString());
                        }
                    }
                    catch
                    {
                    }
                    Run(watchpath);
                }
            }
        }
        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
        public void Run(string path)
        {
            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = path;
            /* Watch for changes in LastAccess and LastWrite times, and
               the renaming of files or directories. */
            watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
               | NotifyFilters.FileName | NotifyFilters.DirectoryName;
            // Only watch text files.
            //watcher.Filter = "*.txt";
            watcher.Filter = "*.TOSKY*";
            watcher.Created += new FileSystemEventHandler(OnChanged);
            //watcher.Changed += new FileSystemEventHandler(OnChanged);
            //watcher.Deleted += new FileSystemEventHandler(OnChanged);
            //watcher.Renamed += new RenamedEventHandler(OnRenamed);

            // Begin watching.
            watcher.EnableRaisingEvents = true;
            watcher.IncludeSubdirectories = true;
            // Wait for the user to quit the program.
            //Console.WriteLine("Press \'q\' to quit the sample.");
            //while (Console.Read() != 'q') ;
        }

        // Define the event handlers. 
        private void OnChanged(object source, FileSystemEventArgs e)
        {
            // Specify what is done when a file is changed, created, or deleted.
            //1. collect all the files
            //2. start transactions.
            //3. then start the 
            string file = e.FullPath;
            if (jobQ == null)
                jobQ = new Queue<KeyValuePair<string, string>>();
            
            FileInfo fileInfo = new FileInfo(file);
            if (fileInfo.Name == "BatchLoadIntexKeyTable.TOSKY")
            {
                BatchUpload();
                File.Delete(file);
                return;
            }
            if (fileInfo.Name == "ReadSkydrive.TOSKY")
            {
                ReadSkydrive();
                File.Delete(file);
                return;
            }
            string folder = fileInfo.DirectoryName;
            folder = folder.Replace(@"C:\IntexReport\PhoneDB\", "");
            if (folder != @"C:\IntexReport\PhoneDB")
            {
                LiveClient.GetFolderID(folder);
            }
            lock (jobQ)
            {
                jobQ.Enqueue(new KeyValuePair<string, string>(file, folder));
            }
            ExecuteJob();
            //  ExecuteJob(file, folder); 
        }
        private async void ExecuteJob(string localfile, string folder)
        {
            LiveOperationResult result = null;
            string destpath = LiveClient.CheckFolderID(folder);
            string filepath = localfile.Replace(".TOSKY", "");
            MemoryStream memStream = new MemoryStream();
            FileInfo file = new FileInfo(filepath);
            string filename = file.Name;
            using (FileStream fileStream = File.OpenRead(filepath))
            {
                memStream.SetLength(fileStream.Length);
                fileStream.Read(memStream.GetBuffer(), 0, (int)fileStream.Length);
            }
            result = await LiveClient.UploadAsync(destpath, filename, memStream, OverwriteOption.Overwrite);
            running++;
            if (result.Error == null)
            {
                System.IO.File.Delete(filepath);
                System.IO.File.Delete(filepath + ".TOSKY");
                running--;
            }
        }
        public async void BatchUpload()
        { 
            jobQ = new Queue<KeyValuePair<string, string>>();
            try
            {
                string[] phondb = System.IO.Directory.GetDirectories(@"C:\IntexReport\PhoneDB");
                foreach (string drs in phondb)
                {
                    string[] files = System.IO.Directory.GetFiles(drs);
                    string folder = drs.Replace(@"C:\IntexReport\PhoneDB\", "");
                    if (folder != @"C:\IntexReport\PhoneDB")
                    {
                        await LiveClient.GetFolderID(folder);
                    }
                    foreach (string file in files)
                    {
                        jobQ.Enqueue(new KeyValuePair<string, string>(file, folder));
                    }
                }
                ExecuteJob();
            }
            catch (Exception ex)
            {
            }
        }
        private async void ReadSkydrive()
        {
            try
            {
                LiveClient.RefreshFileList();
            }
            catch (Exception ex)
            { 
            }
        }
        public async void ExecuteJob()
        {
            LiveOperationResult result;
            try
            {       
                while (jobQ.Count > 0)
                {
                    if (running < 50)
                    {
                        if (jobQ.Count == 0)
                            break;
                        KeyValuePair<string, string> kp = jobQ.Dequeue();
                        try
                        {
                            string localfile = kp.Key;
                            string folder = kp.Value;
                            string destpath = LiveClient.CheckFolderID(folder);
                            string filepath = localfile.Replace(".TOSKY", "");
                            //liveConnectClient.Execute("UPLOAD", localfile.Replace(".TOSKY",""),destpath);
                            MemoryStream memStream = new MemoryStream();
                            FileInfo file = new FileInfo(filepath);
                            string filename = file.Name;
                            using (FileStream fileStream = File.OpenRead(filepath))
                            {
                                memStream.SetLength(fileStream.Length);
                                fileStream.Read(memStream.GetBuffer(), 0, (int)fileStream.Length);
                            }
                            running++;
                            result = await LiveClient.UploadAsync(destpath, filename, memStream, OverwriteOption.Overwrite);
                            running--;
                            if (result.Error == null)
                            {
                                System.IO.File.Delete(filepath);
                                System.IO.File.Delete(filepath + ".TOSKY");
                            }
                        }
                        catch (Exception ex)
                        { 
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }

        private void OnRenamed(object source, RenamedEventArgs e)
        {
            // Specify what is done when a file is renamed.
            Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
        }

        private void ReadConfig()
        {
            string strKey = "";

            try
            {
                if (!System.IO.Directory.Exists(@"C:\IntexReport"))
                {
                    System.IO.Directory.CreateDirectory(@"C:\IntexReport");
                }
                if (!System.IO.Directory.Exists(@"C:\IntexReport\PhoneDB"))
                {
                    System.IO.Directory.CreateDirectory(@"C:\IntexReport\PhoneDB");
                }
                foreach (string key in System.Configuration.ConfigurationSettings.AppSettings)
                {
                    strKey = key.ToString();
                    if (strKey.StartsWith("wpath"))
                    {
                        watchpath.Add(ConfigurationSettings.AppSettings[strKey].ToString());
                    }
                }
            }
            catch (Exception ex)
            {
            }
        }
    }
}